<template>
	<el-form
		ref="formRef"
		style="overflow: auto"
		:model="innerModel"
		:rules="rules"
		:label-width="labelWidth"
		:label-position="labelPosition"
		v-bind="$attrs"
	>
		<template v-for="(t, index) in items" :key="index">
			<div class="form-title" v-if="t?.title">{{ t.title }}</div>
			<el-row class="elRow" :gutter="rowNum">
				<el-col
					v-for="item in t.formList"
					:key="item.prop"
					:span="colNum"
					:offset="offset"
				>
					<!-- input -->
					<el-form-item :label="item.label" :prop="item.prop">
						<!-- 自定义插槽 -->
						<template v-if="item.type === 'slot'">
							<slot :name="item.prop" :model="innerModel" />
						</template>
						<el-input
							v-if="item.type === 'input' || !item.type"
							v-model="innerModel[item.prop]"
							v-bind="item.attrs"
							:placeholder="item?.attrs?.placeholder || '请输入'"
						>
						</el-input>

						<!-- select -->
						<el-select
							v-else-if="item.type === 'select'"
							v-model="innerModel[item.prop]"
							v-bind="item.attrs"
							:empty-values="[null, undefined]"
							:placeholder="item?.attrs?.placeholder || '请选择'"
						>
							<el-option
								v-for="opt in item.options"
								:key="opt.value"
								:label="opt.label"
								:value="opt.value"
							/>
						</el-select>
						<el-radio-group
							v-model="innerModel[item.prop]"
							v-else-if="item.type === 'radio'"
						>
							<el-radio
								:value="opt.value"
								v-for="opt in item.options"
								:key="opt.value"
								>{{ opt.label }}</el-radio
							>
						</el-radio-group>
						<!-- date -->
						<el-date-picker
							v-else-if="item.type === 'date'"
							v-model="innerModel[item.prop]"
							v-bind="item.attrs"
						/>

						<!-- switch -->
						<el-switch
							v-else-if="item.type === 'switch'"
							v-model="innerModel[item.prop]"
							v-bind="item.attrs"
						/>
						<!-- 地址选择器 -->

						<CustomAreaSelect
							v-else-if="item.type === 'areaSelect'"
							v-model="innerModel[item.prop]"
							:placeholder="item?.attrs?.placeholder"
						/>
						<!-- 上传 -->
						<base-upload
							v-else-if="item.type === 'upload'"
							v-model:imgModel="innerModel[item.prop]"
							:width="item?.attrs?.width || '308px'"
							:height="item?.attrs?.height || '181px'"
							action="/api/foundation/client/upload/image"
							:max-size="2"
							:limit="3"
							multiple
							:tip="
								item?.attrs?.tip ||
								`建议上传高度为320px宽度不限的图片，
且大小不超过2M`
							"
							@success="handleSuccess"
						>
						</base-upload>
						<!-- 其余：可自行扩展 -->
						<slot :name="item.type"></slot>
					</el-form-item>
				</el-col>
			</el-row>
		</template>
	</el-form>
</template>

<script setup lang="ts" generic="T extends Record<string, any>">
import type { FormRules, FormItemRule } from 'element-plus'
import type { ProFormItem } from './index'
import BaseUpload from '@/components/baseUpload/index.vue'
import { computed, ref } from 'vue'
import CustomAreaSelect from '@/components/customAreaSelect/index.vue'

interface Props {
	/** 表单数据对象（双向绑定） */
	modelValue: T
	/** 字段配置数组 */
	items: ProFormItem[]
	labelWidth?: number | string
	labelPosition?: string
	colNum?: number
	rowNum?: number
	offset?: number
}

const props = withDefaults(defineProps<Props>(), {
	labelWidth: 'auto',
	labelPosition: 'left',
	colNum: 12,
	rowNum: 80,
	offset: 0,
})
const emit = defineEmits<{
	'update:modelValue': [val: T]
}>()

/* 内部响应式对象，双向绑定 */
const innerModel = computed<T>({
	get: () => props.modelValue,
	set: (val) => emit('update:modelValue', val),
})

/* 自动生成 rules（外部也可覆盖） */
const rules = computed<FormRules>(() => {
	const rulesMap = props.items.reduce<Record<string, FormItemRule[]>>(
		(acc, section) => {
			section.formList.forEach((item) => {
				if (item.rules) acc[item.prop] = item.rules
			})
			return acc
		},
		{}
	)
	return rulesMap
})

/* 暴露方法供外部调用 */
const formRef = ref()
function validate() {
	return formRef.value?.validate()
}
function resetFields() {
	formRef.value?.resetFields()
}
function clearValidate() {
	formRef.value?.clearValidate()
}

defineExpose({ validate, resetFields, clearValidate })
</script>
<style lang="less" scoped>
.form-title {
	margin-top: 30px;
	font-weight: 500;
	font-size: 16px;
	color: #006d7a;
	position: relative;
	padding-left: 4px;
	line-height: 32px;
	&::before {
		position: absolute;
		content: '';
		left: 0;
		top: 50%;
		transform: translateY(-50%);
		width: 2px;
		height: 12px;
		background: #006d7a;
		border-radius: 0px 0px 0px 0px;
	}
}
.elRow {
	width: 100%;
}
:deep(.el-form-item__label) {
	font-family: Roboto, Roboto;
	font-weight: 500;
	font-size: 16px;
	color: #000000;
	position: relative;
	&::before {
		position: absolute;
		right: -1px;
	}
}
:deep(.el-form-item) {
	width: 100%;
}
:deep(.el-input__inner) {
}
:deep(.el-select__placeholder) {
	span {
		font-weight: 400;
		font-size: 14px;
		// color: #000000;
	}
}
:deep(.el-input.is-disabled) {
	.el-input__wrapper {
		background-color: transparent;
	}
	.el-input__inner {
		-webkit-text-fill-color: #000000;
	}
}
</style>
